/**
 * Copyright: Copyright (c) 2016, 湖南强智科技发展有限公司
 */

package com.qzdatasoft.mcp.server.common;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * 线程变量 管理器<br>
 * <br>
 * History:<br>
 *    . v3.0.0.20201025, com.qzdatasoft.WangShi, Create<br>
 */
public class RequestThreadLocal {
    private static final Logger log = LoggerFactory.getLogger(RequestThreadLocal.class);
    private final static ConcurrentMap<String, InheritableThreadLocal<?>> map = new ConcurrentHashMap<String, InheritableThreadLocal<?>>();

    private RequestThreadLocal() {
    }

    /**
     * 读取线程变量
     * @param key
     * @param <T>
     * @return
     */
    public static <T> T get(String key) {
        Optional<InheritableThreadLocal> op = Optional.ofNullable(map.get(key));
        if (op.isPresent()) {
            InheritableThreadLocal threadLocal = op.get();
            Object data = threadLocal.get();

            if (log.isDebugEnabled()) {
                log.debug("RequestThreadLocal.get{}: {}", StringUtils.capitalize(key), data);
            }

            return (T) data;
        }

        log.warn("RequestThreadLocal[{}]  is not exist.", key);
        return null;
    }

    /**
     * 设置线程变量
     * @param key
     * @param value
     */
    public static void set(String key, Object value) {
        InheritableThreadLocal threadLocal;

        Optional<InheritableThreadLocal> op = Optional.ofNullable(map.get(key));
        if (op.isPresent()) {
            threadLocal = op.get();
        } else {
            threadLocal = register(key);
        }

        threadLocal.set(value);

        if (log.isDebugEnabled()) {
            log.debug("RequestThreadLocal.set{}: {}", StringUtils.capitalize(key), value);
        }

    }

    /**
     * 销毁线程变量
     * @param key
     */
    public static void remove(String key) {
        Optional op = Optional.ofNullable(map.get(key));
        if (op.isPresent()) {

            InheritableThreadLocal threadLocal = (InheritableThreadLocal) op.get();
            threadLocal.remove();

            if (log.isDebugEnabled()) {
                log.debug("RequestThreadLocal.remove{}.", StringUtils.capitalize(key));
            }
        }
    }

    /**
     *  注册线程变量 String key = T value>
     * @param key
     * @return
     */
    private static InheritableThreadLocal register(String key) {
        InheritableThreadLocal re = new InheritableThreadLocal();
        map.put(key, re);
        log.debug("RequestThreadLocal[{}] has registered.", key);
        return re;
    }

}
